//
// Created by 邹嘉旭 on 2025/8/8.
//

#include <ld_bitset.h>
#include "interface/ground.h"
#include "as_entity.h"
#include "amm.h"
#include "define.h"
#include "interface/gs1.h"


static field_desc g1_sac_rqst_fields[] = {
    {ft_set, 8, "GTYPE", NULL},
    {ft_set, 4, "VERSION", NULL},
    {ft_set, 28, "AS UA", NULL},
    {ft_pad, 0, "PAD", NULL},
    {ft_end, 0, NULL, NULL},
};
struct_desc_t g1_sac_rqst_desc = {"G1 SAC REQUEST", g1_sac_rqst_fields};

static field_desc g1_sac_resp_fields[] = {
    {ft_set, 8, "GTYPE", NULL},
    {ft_set, 4, "VERSION", NULL},
    {ft_set, 12, "AS SAC", NULL},
    {ft_set, 28, "AS UA", NULL},
    {ft_pad, 0, "PAD", NULL},
    {ft_end, 0, NULL, NULL},
};
struct_desc_t g1_sac_resp_desc = {"G1 SAC RESPONSE", g1_sac_resp_fields};


static l_err recv_g1_sac_rqst(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_sac_resp(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_init_as(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_snf_upload(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_snf_download(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_key_trans(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_bearer_est_rqst(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_bearer_est_resp(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_as_exit(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_release_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_ho_rqst_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_key_update_remind_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_path_switch_request_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_path_switch_response_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_ho_rqst_ack_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);
static l_err recv_g1_as_st_chg_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt);

size_t g1_format_size = 16;
cn_format_desc_t g1_format_descs[] = {
    {G1_SAC_RQST, &g1_sac_rqst_desc, "G1 SAC RQST", sizeof(g1_sac_rqst_t), 5, default_cn_send_handler, recv_g1_sac_rqst, NULL, free},
    {G1_SAC_RESP, &g1_sac_resp_desc, "G1 SAC RESP", sizeof(g1_sac_resp_t), 7, default_cn_send_handler, recv_g1_sac_resp, NULL, free},
    {G1_INIT_AS, &g1_g3_init_as_desc, "G1 G3 INIT AS", sizeof(g1_g3_init_as_t), 0, default_cn_send_handler , recv_g1_init_as, NULL, free_g1_g3_init_as},
    {G1_SNF_UPLOAD, &g1_g3_snf_pkt_desc, "G1 G3 UPLOAD DESC", sizeof(g1_g3_snf_pkt_t), 0, NULL, recv_g1_snf_upload, default_cn_forward_handler, free_g1_g3_snf_pkt},
    {G1_SNF_DOWNLOAD, &g1_g3_snf_pkt_desc, "G1 G3 DOWNLOAD DESC", sizeof(g1_g3_snf_pkt_t), 0, default_cn_send_handler, recv_g1_snf_download, default_cn_forward_handler, free_g1_g3_snf_pkt},
    {G1_KEY_TRANS, &g1_g3_snf_pkt_desc, "G1 G3 KEY TRANS", sizeof(g1_g3_snf_pkt_t), 0, NULL, recv_g1_key_trans, default_cn_forward_handler, free_g1_g3_snf_pkt},
    {G1_DATA_BEARER_EST_RQST, &g1_g5_bearer_est_desc, "G1 G5 BEARER EST RQST", sizeof(g1_g5_bearer_est_t), 0, NULL, recv_g1_bearer_est_rqst, default_cn_forward_handler, free_g1_g5_bearer_est},
    {G1_DATA_BEARER_EST_RESP, &g1_g5_bearer_est_desc, "G1 G5 BEARER EST RESP", sizeof(g1_g5_bearer_est_t), 0, default_cn_send_handler, recv_g1_bearer_est_resp, NULL, free_g1_g5_bearer_est},
    {G1_AS_EXIT, &g1_g5_as_release_exit_desc, "G1 G5 AS EXIT", sizeof(g1_g5_as_release_exit_t), 3, default_cn_send_handler, recv_g1_as_exit, NULL, free},
    {G1_RELEASE_AS_CONTEXT, &g1_g5_as_release_exit_desc, "G1 G5 AS RELEASE CONTEXT", sizeof(g1_g5_as_release_exit_t), 3, default_cn_send_handler, recv_g1_release_ctx, NULL, free},
    {G1_HANDOVER_REQUEST, &g1_handover_request_desc, "G1 HANDOVER REQUEST", sizeof(g1_ho_rqst_t), 6, default_cn_send_handler, recv_g1_ho_rqst_ctx, default_cn_forward_handler, free},
    {G1_KEY_UPDATE_REMIND, &g1_g3_key_update_remind_desc, "G1 G3 KEY UPDATE REMIND", sizeof(g1_g3_key_update_remind_t), 7, default_cn_send_handler, recv_g1_key_update_remind_ctx, NULL, free},
    {G1_PATH_SWITCH_REQUEST, &g1_g5_path_switch_desc, "G1 G5 PATH SWITCH REQUEST", sizeof(g1_g5_path_switch_t), 21, default_cn_send_handler, recv_g1_path_switch_request_ctx, NULL, free_g1_g5_path_switch},
    {G1_PATH_SWITCH_RESPONSE, &g1_g5_path_switch_desc, "G1 G5 PATH SWITCH RESPONSE", sizeof(g1_g5_path_switch_t), 21, NULL, recv_g1_path_switch_response_ctx, default_cn_forward_handler, free_g1_g5_path_switch},
    {G1_HANDOVER_REQUEST_ACK, &g1_ho_rqst_ack_desc, "G1 HO RQST ACK", sizeof(g1_ho_rqst_ack_t), 5, default_cn_send_handler, recv_g1_ho_rqst_ack_ctx, default_cn_forward_handler,  free},
    {G1_AS_STATE_CHANGE, &g1_g3_g5_as_st_chg_desc, "G1 AS STATE CHANGE", sizeof(g1_g3_g5_as_st_chg_t), 5, default_cn_send_handler, recv_g1_as_st_chg_ctx, NULL,  free},
};


static l_err recv_g1_sac_rqst(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {

    g1_sac_rqst_t *rqst = NULL;
    if ((rqst = parse_sdu(in_buf, desc->f_desc, desc->struct_size)) == NULL) {
        log_error("Parse SDU failed!");
        if (rqst)    desc->free_func(rqst);
        return LD_ERR_INTERNAL;
    }

    meta_service_t *meta = net_ele->meta_map[INTERFACE_G1];
    amm_entity_t *amm_entity = net_ele->inline_element;

    if (!has_as_uenode(net_ele->as_map, rqst->AS_UA)) {

        // 分配SAC
        uint64_t index = bs_get_lowest_unalloced(amm_entity->sac_bitset);
        bs_record_by_index(amm_entity->sac_bitset, index);
        as_entity_t *as = init_as_entity(rqst->AS_UA, TO_SAC(index), propt->peer_sac, ELEMENT_AMM, net_ele);
        set_as_enode(net_ele->as_map, as);


        g1_sac_resp_t resp = {
                .GTYPE = G1_SAC_RESP, .VERSION = CN_VERSION, .AS_SAC = as->SAC, .AS_UA = as->UA
        };

        cn_format_desc_t *send_desc = get_non_sequential_desc(g1_format_size, g1_format_descs, G1_SAC_RESP);
        if (!send_desc || !send_desc->send_handler || send_desc->send_handler(
                net_ele,
                &resp,
                send_desc,
                get_propt(net_ele, INTERFACE_G1, as->current_client_peer_sac),
                INTERFACE_G1
            ) != LD_OK) {
            cn_log_error(net_ele->element_tag, INTERFACE_G1, "Failed to send");
            desc->free_func(rqst);
            return LD_ERR_NULL;
        }

        desc->free_func(rqst);
        return LD_OK;
    }
    cn_log_error(net_ele->element_tag, meta->interface_type, "Can not repeatly access AS.");
    desc->free_func(rqst);
    return LD_ERR_INVALID;
}

static l_err recv_g1_sac_resp(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    g1_sac_resp_t *resp = NULL;
    if ((resp = parse_sdu(in_buf, desc->f_desc, desc->struct_size)) == NULL) {
        log_error("Parse SDU failed!");
        if (resp)    desc->free_func(resp);
        return LD_ERR_INTERNAL;
    }


    as_entity_t *as = get_as_uenode_by_UA(net_ele->as_map, resp->AS_UA);
    as->SAC = resp->AS_SAC;
    if (!as) {
        cn_log_error(net_ele->element_tag, INTERFACE_GS1, "No such AS: %d.", resp->AS_UA);
        desc->free_func(resp);
        return LD_ERR_INVALID;
    }

    if (change_state(&as->gsg_sm, EV_DEFAULT,
                     &(fsm_event_data_t){
                         &gsg_fsm_events[GSG_CONNECTED], NULL})) {
        cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "cant change state correctly");
        desc->free_func(resp);
        return LD_ERR_INVALID;
    }

    /**************** 发送GS1_SAC_RESP *******************/
    gs1_sac_resp_t gs1_sac_resp = {
        .TYPE = GS1_SAC_RESP,
        .AS_UA = resp->AS_UA,
        .AS_SAC = resp->AS_SAC,
    };

    cn_format_desc_t *send_desc = &gs1_format_descs[GS1_SAC_RESP];
    if (!send_desc || !send_desc->send_handler || send_desc->send_handler(
            net_ele,
            &gs1_sac_resp,
            send_desc,
            get_propt(net_ele, INTERFACE_GS1, as->current_client_peer_sac),
            INTERFACE_GS1
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_GS1, "Failed to send");
        desc->free_func(resp);
        return LD_ERR_NULL;
    }

    desc->free_func(resp);

    return LD_OK;
}

static l_err recv_g1_init_as(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    g1_g3_init_as_t *init = calloc(1, sizeof(g1_g3_init_as_t));
    // init->sdu = init_buffer_ptr(in_buf->len - G1_G3_AS_INI_HEAD_LEN);
    PARSE_DSTR_PKT(in_buf, init, sdu, g1_g3_init_as_desc, G1_G3_AS_INI_HEAD_LEN, 0)

    as_entity_t *as = get_as_uenode_by_UA(net_ele->as_map, init->AS_UA);
    if (!as) {
        desc->free_func(init);
        cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "No such AS, which SAC = %d", init->AS_SAC);
        return LD_ERR_INTERNAL;
    }
    cn_format_desc_t *send_desc = get_non_sequential_desc(g3_format_size, g3_format_descs, G3_INIT_AS);
    if (!send_desc || !send_desc->forward_handler || send_desc->forward_handler(
            net_ele,
            in_buf,
            get_propt(net_ele, INTERFACE_G3, 0),
            INTERFACE_G3
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_G3, "Failed to send");
        desc->free_func(init);
        return LD_ERR_NULL;
    }
    desc->free_func(init);
    return LD_OK;
}


static l_err recv_g1_snf_upload(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {


    g1_g3_snf_pkt_t *upload = calloc(1, sizeof(g1_g3_snf_pkt_t));
    // upload->sdu = init_buffer_ptr(in_buf->len - G1_G3_G5_PKT_HEAD_LEN);
    PARSE_DSTR_PKT(in_buf, upload, sdu, g1_g3_snf_pkt_desc, G1_G3_G5_PKT_HEAD_LEN, 0)

    as_entity_t *as = get_as_uenode_by_SAC(net_ele->as_map, upload->AS_SAC);
    if (!as) {
        desc->free_func(upload);
        cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "No such AS, which SAC = %d", upload->AS_SAC);
        return LD_ERR_INTERNAL;
    }

    gs1_snf_pkt_t gs1_upload = {
        .TYPE = GS1_SNF_UPLOAD,
        .AS_SAC = upload->AS_SAC,
        .sdu = init_buffer_unptr(),
    };


    CLONE_TO_CHUNK(*gs1_upload.sdu, upload->sdu->ptr, upload->sdu->len);

    cn_format_desc_t *send_desc = &gs1_format_descs[GS1_SNF_UPLOAD];
    if (!send_desc || !send_desc->send_handler || send_desc->send_handler(
            net_ele,
            &gs1_upload,
            send_desc,
            get_propt(net_ele, INTERFACE_GS1, as->current_client_peer_sac),
            INTERFACE_GS1
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_GS1, "Failed to send");
        desc->free_func(upload);
        free_buffer(gs1_upload.sdu);
        return LD_ERR_NULL;
    }
    free_buffer(gs1_upload.sdu);
    desc->free_func(upload);
    return LD_OK;
}

static l_err recv_g1_snf_download(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {

    g1_g3_snf_pkt_t *download = calloc(1, sizeof(g1_g3_snf_pkt_t));
    // download->sdu = init_buffer_ptr(in_buf->len - G1_G3_G5_PKT_HEAD_LEN);
    PARSE_DSTR_PKT(in_buf, download, sdu, g1_g3_snf_pkt_desc, G1_G3_G5_PKT_HEAD_LEN, 0)

    as_entity_t *as = get_as_uenode_by_SAC(net_ele->as_map, download->AS_SAC);
    if (!as) {
        desc->free_func(download);
        cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "No such AS, which SAC = %d", download->AS_SAC);
        return LD_ERR_INTERNAL;
    }
    cn_format_desc_t *send_desc = get_non_sequential_desc(g3_format_size, g3_format_descs, G3_SNF_DOWNLOAD);

    if (!send_desc || !send_desc->forward_handler || send_desc->forward_handler(
            net_ele,
            in_buf,
            get_propt(net_ele, INTERFACE_G3, 0),
            INTERFACE_G3
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_G3, "Failed to send");
        desc->free_func(download);
        return LD_ERR_NULL;
        }
    desc->free_func(download);
    return LD_OK;
}

static l_err recv_g1_key_trans(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    g1_g3_snf_pkt_t *upload = calloc(1, sizeof(g1_g3_snf_pkt_t));
    // upload->sdu = init_buffer_ptr(in_buf->len - G1_G3_G5_PKT_HEAD_LEN);
    PARSE_DSTR_PKT(in_buf, upload, sdu, g1_g3_snf_pkt_desc, G1_G3_G5_PKT_HEAD_LEN, 0)

    as_entity_t *as = get_as_uenode_by_SAC(net_ele->as_map, upload->AS_SAC);
    if (!as) {
        desc->free_func(upload);
        cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "No such AS, which SAC = %d", upload->AS_SAC);
        return LD_ERR_INTERNAL;
    }

    gs1_snf_pkt_t gs1_key_tran = {
        .TYPE = GS1_KEY_TRANS,
        .AS_SAC = upload->AS_SAC,
        .sdu = init_buffer_unptr(),
    };

    CLONE_TO_CHUNK(*gs1_key_tran.sdu, upload->sdu->ptr, upload->sdu->len);

    cn_format_desc_t *send_desc = &gs1_format_descs[GS1_KEY_TRANS];
    if (!send_desc || !send_desc->send_handler || send_desc->send_handler(
            net_ele,
            &gs1_key_tran,
            send_desc,
            get_propt(net_ele, INTERFACE_GS1, 0),
            INTERFACE_GS1
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_GS1, "Failed to send");
        desc->free_func(upload);
        free_buffer(gs1_key_tran.sdu);
        return LD_ERR_NULL;
        }
    free_buffer(gs1_key_tran.sdu);
    desc->free_func(upload);
    return LD_OK;
}

static l_err recv_g1_bearer_est_rqst(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    g1_g5_bearer_est_t *bearer = calloc(1, sizeof(g1_g5_bearer_est_t));
    //bearer->IP = init_buffer_ptr((GEN_ADDRLEN));
    PARSE_DSTR_PKT(in_buf, bearer, snf_msg, g1_g5_bearer_est_desc, G1_G3_G5_PKT_HEAD_LEN, (GEN_ADDRLEN) + 2)

    as_entity_t *as = get_as_uenode_by_SAC(net_ele->as_map, bearer->AS_SAC);

    if (!as) {
        desc->free_func(bearer);
        cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "No such AS, which SAC = %d", bearer->AS_SAC);
        return LD_ERR_INTERNAL;
    }

    gs1_snf_pkt_t snf_pkt = {
        .TYPE = GS1_UP_UPLOAD_TRANSPORT,
        .AS_SAC = bearer->AS_SAC,
        .sdu = init_buffer_unptr(),
    };

    CLONE_TO_CHUNK(*snf_pkt.sdu, bearer->snf_msg->ptr, bearer->snf_msg->len);

    cn_format_desc_t *send_desc = &gs1_format_descs[GS1_UP_UPLOAD_TRANSPORT];
    if (!send_desc || !send_desc->send_handler || send_desc->send_handler(
            net_ele,
            &snf_pkt,
            send_desc,
            get_propt(net_ele, INTERFACE_GS1, as->current_client_peer_sac),
            INTERFACE_GS1
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_GS1, "Failed to send");
        free_buffer(snf_pkt.sdu);
        desc->free_func(bearer);
        return LD_ERR_NULL;
        }


    free_buffer(snf_pkt.sdu);
    desc->free_func(bearer);
    return LD_OK;
}

static l_err recv_g1_bearer_est_resp(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    g1_g5_bearer_est_t *bearer = calloc(1, sizeof(g1_g5_bearer_est_t));
    //bearer->IP = init_buffer_ptr((GEN_ADDRLEN));
    PARSE_DSTR_PKT(in_buf, bearer, snf_msg, g1_g5_bearer_est_desc, G1_G3_G5_PKT_HEAD_LEN, (GEN_ADDRLEN) + 2)

    as_entity_t *as = get_as_uenode_by_SAC(net_ele->as_map, bearer->AS_SAC);

    if (!as) {
        desc->free_func(bearer);
        cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "No such AS, which SAC = %d", bearer->AS_SAC);
        return LD_ERR_INTERNAL;
    }

    set_as_gs_ip(as, (char *)bearer->IP->ptr, bearer->port);

    cn_format_desc_t *send_desc = get_non_sequential_desc(g5_format_size, g5_format_descs, G5_DATA_BEARER_EST_RESP);
    if (!send_desc || !send_desc->forward_handler || send_desc->forward_handler(
            net_ele,
            in_buf,
            get_propt(net_ele, INTERFACE_G5, 0),
            INTERFACE_G5
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_G5, "Failed to send");
        desc->free_func(bearer);
        return LD_ERR_NULL;
    }

    desc->free_func(bearer);
    return LD_OK;
}

static l_err recv_g1_as_exit(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf,
                                  element_propt_t *propt) {

    g1_g5_as_release_exit_t *exit = NULL;
    if ((exit = parse_sdu(in_buf, desc->f_desc, desc->struct_size)) == NULL) {
        log_error("Parse SDU failed!");
        if (exit)    desc->free_func(exit);
        return LD_ERR_INVALID;
    }

    as_entity_t *as = get_as_uenode_by_SAC(net_ele->as_map, exit->AS_SAC);
    if (!as) {
        cn_log_error(net_ele->element_tag, INTERFACE_G1, "No such AS: %d.", exit->AS_SAC);
        desc->free_func(exit);
        return LD_ERR_INVALID;
    }

    cn_format_desc_t *send_desc = get_non_sequential_desc(g5_format_size, g5_format_descs, G5_AS_EXIT);
    if (!send_desc || !send_desc->forward_handler || send_desc->forward_handler(
            net_ele,
            in_buf,
            get_propt(net_ele, INTERFACE_G5, 0),
            INTERFACE_G5
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_G5, "Failed to send");
        desc->free_func(exit);
        return LD_ERR_NULL;
    }


    desc->free_func(exit);
    return LD_OK;
}

static l_err recv_g1_release_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    g1_g5_as_release_exit_t *release = NULL;
    if ((release = parse_sdu(in_buf, desc->f_desc, desc->struct_size)) == NULL) {
        log_error("Parse SDU failed!");
        if (release)    desc->free_func(release);
        return LD_ERR_INVALID;
    }

    as_entity_t *as = get_as_uenode_by_SAC(net_ele->as_map, release->AS_SAC);
    if (!as) {
        cn_log_error(net_ele->element_tag, INTERFACE_G1, "No such AS: %d.", release->AS_SAC);
        desc->free_func(release);
        return LD_ERR_INVALID;
    }


    // cn_log_warn(net_ele->element_tag, INTERFACE_UNDEFINED, "%d",in_state(&as->gsg_sm, "GSG_INITIAL"));
    // cn_log_warn(net_ele->element_tag, INTERFACE_UNDEFINED, "%d",in_state(&as->gsg_sm, "GSG_SAC_ALLOCING"));
    // cn_log_warn(net_ele->element_tag, INTERFACE_UNDEFINED, "%d",in_state(&as->gsg_sm, "GSG_CONNECTED"));
    // cn_log_warn(net_ele->element_tag, INTERFACE_UNDEFINED, "%d",in_state(&as->gsg_sm, "GSG_HO_OTHER"));
    // cn_log_warn(net_ele->element_tag, INTERFACE_UNDEFINED, "%d",in_state(&as->gsg_sm, "GSG_HO_CURRENT"));
    // cn_log_warn(net_ele->element_tag, INTERFACE_UNDEFINED, "%d",in_state(&as->gsg_sm, "GSG_EXIT"));

    if (in_state(&as->gsg_sm, "GSG_CONNECTED")) {
        if (change_state(&as->gsg_sm, EV_DEFAULT,
                         &(fsm_event_data_t){
                             &gsg_fsm_events[GSG_EXIT], NULL})) {
            cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "cant change state correctly");
            desc->free_func(release);
            return LD_ERR_INVALID;
        }
    }else {
        cn_log_warn(net_ele->element_tag, INTERFACE_G1, "Wrong status");
    }

    if (delete_element_uenode_by_SAC(net_ele->as_map, as->SAC) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "Failed to delete as entity");
        desc->free_func(release);
        return LD_ERR_INVALID;
    }

    desc->free_func(release);
    return LD_OK;
}

static l_err recv_g1_ho_rqst_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    g1_ho_rqst_t *g1_rqst = NULL;

    if ((g1_rqst = parse_sdu(in_buf, desc->f_desc, desc->struct_size)) == NULL) {
        log_error("Parse SDU failed!");
        if (g1_rqst)    desc->free_func(g1_rqst);
        return LD_ERR_INVALID;
    }


    if (net_ele->element_type == ELEMENT_AMM) {
        as_entity_t *as = get_as_uenode_by_SAC(net_ele->as_map, g1_rqst->AS_SAC);
        if (!as) {
            cn_log_error(net_ele->element_tag, INTERFACE_G1, "No such AS: %d.", g1_rqst->AS_SAC);
            desc->free_func(g1_rqst);
            return LD_ERR_INVALID;
        }
        // AMM
        as->next_peer_sac = g1_rqst->GST_SAC;

        if (!in_state(&as->amm_sm, "AMM_CONNECTED")) {
            cn_log_warn(net_ele->element_tag, INTERFACE_G1, "Wrong status");
        }else {
            if (change_state(&as->amm_sm, EV_DEFAULT,
                             &(fsm_event_data_t){
                                 &amm_fsm_events[AMM_HO_PREPARE], NULL})) {
                cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "cant change state correctly");
                desc->free_func(g1_rqst);
                return LD_ERR_INVALID;
            }
        }


        cn_format_desc_t *forward_desc = get_non_sequential_desc(g1_format_size, g1_format_descs, G1_HANDOVER_REQUEST);
        if (!forward_desc || !forward_desc->forward_handler || forward_desc->forward_handler(
                net_ele,
                in_buf,
                get_propt(net_ele, INTERFACE_G1, g1_rqst->GST_SAC),
                INTERFACE_G1
            ) != LD_OK) {
            cn_log_error(net_ele->element_tag, INTERFACE_G1, "Failed to send");
            desc->free_func(g1_rqst);
            return LD_ERR_NULL;
            }

    }else {
        // GSG_011

        as_entity_t *as = NULL;
        if (!has_as_uenode(net_ele->as_map, g1_rqst->AS_UA)) {
            as = init_as_entity(g1_rqst->AS_UA, g1_rqst->AS_SAC, g1_rqst->GSS_SAC, ELEMENT_GSG, net_ele);
            as->next_peer_sac = g1_rqst->GST_SAC;


            if (change_state(&as->gsg_sm, EV_DEFAULT,
                             &(fsm_event_data_t){
                                 &gsg_fsm_events[GSG_CONNECTED], NULL})) {
                cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "cant change state correctly");
                desc->free_func(g1_rqst);
                return LD_ERR_INVALID;
            }

            set_as_enode(net_ele->as_map, as);

        }else {
            cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "Current GSG has AS: %d", g1_rqst->AS_SAC);
            return LD_ERR_INVALID;
        }

        g1_g3_key_update_remind_t remind = {
            .GTYPE = G1_KEY_UPDATE_REMIND,
            .VERSION = CN_VERSION,
            .AS_SAC = as->SAC,
            .element_type = 0xC,
            .GSS_SAC = g1_rqst->GSS_SAC,
            .GST_SAC = g1_rqst->GST_SAC,
        };

        cn_format_desc_t *send_desc = get_non_sequential_desc(g1_format_size, g1_format_descs, G1_KEY_UPDATE_REMIND);
        if (!send_desc || !send_desc->send_handler || send_desc->send_handler(
                net_ele,
                &remind,
                send_desc,
                get_propt(net_ele, INTERFACE_G1, 0),
                INTERFACE_G1
            ) != LD_OK) {
            cn_log_error(net_ele->element_tag, INTERFACE_G1, "Failed to send");
        desc->free_func(g1_rqst);
            return LD_ERR_NULL;
        }


        client_interface_t *cli_int = get_client_interface(net_ele, INTERFACE_G1U);

        // 发送 path switch request
        g1_g5_path_switch_t switch_request = {
            .GTYPE = G1_PATH_SWITCH_REQUEST,
            .VERSION = CN_VERSION,
            .AS_SAC = as->SAC,
            .IP = init_buffer_unptr(),
            .port = cli_int->local_port,
        };

        struct in6_addr addr;
        inet_pton(AF_INET6, cli_int->local_addr_v6, &addr);
        CLONE_TO_CHUNK(*switch_request.IP, addr.__in6_u.__u6_addr8, GEN_ADDRLEN);

        cn_format_desc_t *send_desc_rqst = get_non_sequential_desc(g1_format_size, g1_format_descs,
                                                                   G1_PATH_SWITCH_REQUEST);
        if (!send_desc_rqst || !send_desc_rqst->send_handler || send_desc_rqst->send_handler(
                net_ele,
                &switch_request,
                send_desc_rqst,
                get_propt(net_ele, INTERFACE_G1, 0),
                INTERFACE_G1
            ) != LD_OK) {
            cn_log_error(net_ele->element_tag, INTERFACE_G1, "Failed to send");
            free_buffer(switch_request.IP);
            desc->free_func(g1_rqst);
            return LD_ERR_NULL;
        }


        free_buffer(switch_request.IP);
    }

        desc->free_func(g1_rqst);
    return LD_OK;
}

static l_err recv_g1_key_update_remind_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    cn_format_desc_t *send_desc = get_non_sequential_desc(g3_format_size, g3_format_descs, G3_KEY_UPDATE_REMIND);
    if (!send_desc || !send_desc->forward_handler || send_desc->forward_handler(
            net_ele,
            in_buf,
            get_propt(net_ele, INTERFACE_G3, 0),
            INTERFACE_G3
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_G3, "Failed to send");
        return LD_ERR_NULL;
    }

    return LD_OK;
}

static l_err recv_g1_path_switch_request_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    cn_format_desc_t *send_desc = get_non_sequential_desc(g5_format_size, g5_format_descs, G5_PATH_SWITCH_REQUEST);
    if (!send_desc || !send_desc->forward_handler || send_desc->forward_handler(
            net_ele,
            in_buf,
            get_propt(net_ele, INTERFACE_G5, 0),
            INTERFACE_G5
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_G5, "Failed to send");
        return LD_ERR_NULL;
        }

    return LD_OK;
}

static l_err recv_g1_path_switch_response_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {

    g1_g5_path_switch_t *rqst = NULL;
    if ((rqst = parse_sdu(in_buf, desc->f_desc, desc->struct_size)) == NULL) {
        log_error("Parse SDU failed!");
        if (rqst)    desc->free_func(rqst);
        return LD_ERR_INVALID;
    }

    as_entity_t *as = get_as_uenode_by_SAC(net_ele->as_map, rqst->AS_SAC);
    if (!as) {
        cn_log_error(net_ele->element_tag, INTERFACE_G1, "No such AS: %d.", rqst->AS_SAC);
        desc->free_func(rqst);
        return LD_ERR_INVALID;
    }

    set_as_as_ip(as, (char *)rqst->IP->ptr);

    desc->free_func(rqst);
    return LD_OK;
}

static l_err recv_g1_ho_rqst_ack_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    g1_ho_rqst_ack_t *ack = NULL;

    if ((ack = parse_sdu(in_buf, desc->f_desc, desc->struct_size)) == NULL) {
        log_error("Parse SDU failed!");
        if (ack)    desc->free_func(ack);
        return LD_ERR_INVALID;
    }

    as_entity_t *as = get_as_uenode_by_SAC(net_ele->as_map, ack->AS_SAC);
    if (!as) {
        cn_log_error(net_ele->element_tag, INTERFACE_G1, "No such AS: %d.", ack->AS_SAC);
        desc->free_func(ack);
        return LD_ERR_INVALID;
    }

    if (net_ele->element_type == ELEMENT_AMM) {

        cn_format_desc_t *forward_desc = get_non_sequential_desc(g1_format_size, g1_format_descs, G1_HANDOVER_REQUEST_ACK);
        if (!forward_desc || !forward_desc->forward_handler || forward_desc->forward_handler(
                net_ele,
                in_buf,
                get_propt(net_ele, INTERFACE_G1, as->current_client_peer_sac),
                INTERFACE_G1
            ) != LD_OK) {
            cn_log_error(net_ele->element_tag, INTERFACE_G1, "Failed to send");
            desc->free_func(ack);
            return LD_ERR_NULL;
            }

    }else {
        gs1_ho_rqst_ack_t gs1_ack = {
            .TYPE = GS1_HO_REQUEST_ACK,
            .AS_SAC = ack->AS_SAC,
            .NEXT_CO = ack->NEXT_CO,
        };

        cn_format_desc_t *send_desc = &gs1_format_descs[GS1_HO_REQUEST_ACK];
        if (!send_desc || !send_desc->send_handler || send_desc->send_handler(
                net_ele,
                &gs1_ack,
                send_desc,
                get_propt(net_ele, INTERFACE_GS1, 0),
                INTERFACE_GS1
            ) != LD_OK) {
            cn_log_error(net_ele->element_tag, INTERFACE_G1, "Failed to send");
            desc->free_func(ack);
            return LD_ERR_NULL;
            }

    }

    desc->free_func(ack);
    return LD_OK;
}

static l_err recv_g1_as_st_chg_ctx(net_element_t *net_ele, cn_format_desc_t *desc, buffer_t *in_buf, element_propt_t *propt) {
    g1_g3_g5_as_st_chg_t *chg = NULL;
    if ((chg = parse_sdu(in_buf, desc->f_desc, desc->struct_size)) == NULL) {
        log_error("Parse SDU failed!");
        return LD_ERR_INVALID;
    }

    cn_format_desc_t *forward_desc = get_non_sequential_desc(g5_format_size, g5_format_descs, G5_AS_STATE_CHANGE);
    if (!forward_desc || !forward_desc->forward_handler || forward_desc->forward_handler(
            net_ele,
            in_buf,
            get_propt(net_ele, INTERFACE_G5, 0),
            INTERFACE_G5
        ) != LD_OK) {
        cn_log_error(net_ele->element_tag, INTERFACE_G5, "Failed to send");
        desc->free_func(chg);
        return LD_ERR_NULL;
    }

    desc->free_func(chg);
    return LD_OK;
}
